package com.neusoft.hifly.commons.database;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.neusoft.hifly.commons.lang.StringConstants;
import com.neusoft.hifly.commons.lang.StringUtil;
import com.neusoft.hifly.core.log.Log;

/**
 * Title: 核心类库
 * <p>
 * Description: SQL工具类（支持多数据库）
 * <p>
 * 注意，该工具类适用于Hibernate的HQL语句，其参数是都不带单引号的，所有参数需要使用HQL指定的赋值方式赋值。
 * <p>
 * 若在JDBC中使用SQL语句，注意单引号的追加
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 东软汉枫
 *
 * @author lh_neu
 * @version 1.0.0
 */
public class SQLUtil {
	/**
	 * 数据库类型 oracle
	 */
	public static final String DB_ORACLE = "oracle";

	/**
	 * 数据库类型 edb
	 */
	public static final String DB_EDB = "edb";

	/**
	 * 数据库类型 mysql
	 */
	public static final String DB_MYSQL = "mysql";

	/**
	 * 数据库类型 sqlserver
	 */
	public static final String DB_SQLSERVER = "sqlserver";

	/**
	 * 数据库类型 sybase
	 */
	public static final String DB_SYBASE = "sybase";

	/**
	 * 数据库类型 db2
	 */
	public static final String DB_DB2 = "db2";

	/**
	 * 国产：南大通用数据库 gbase
	 */
	public static final String DB_GBASE = "gbase";

	/**
	 * 数据库类型.oracle、sqlserver、mysql、sybase、gbase ...
	 * <p>
	 * 需要配置文件初始化配置
	 */
	private static String dbType;

	/**
	 * 替换特殊字符
	 * <p>
	 * 将字符串中的单引号根据数据库类型进行相应替换。例如：
	 * <p>
	 * Input -> chinact'ctd
	 * <p>
	 * Output -> chinact' ||chr(39)|| 'ctd
	 *
	 * @author lh_neu
	 * @param str
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @return 转义后的字符
	 */
	public static String replaceStr(final String str) {
		return SQLUtil.replaceStr(SQLUtil.dbType, str);
	}

	/**
	 * 替换特殊字符
	 * <p>
	 * 这里本来想使用StringEscapeUtils.escapeSql(str)，但是查看commons-lang源代码后，发现，该方法只调用了StringUtil.replace(str, "'",
	 * "''");无任何意义，而且commons-lang3已经去掉该方法了
	 * <p>
	 * 将字符串中的单引号根据数据库类型进行相应替换。例如：
	 * <p>
	 * Input -> chinact'ctd
	 * <p>
	 * Output -> chinact' ||chr(39)|| 'ctd
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param str
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @return 转义后的字符
	 */
	public static String replaceStr(final String dbType, final String str) {
		// String replaceStr = StringUtils.trimToEmpty(str); 这里不能去掉左右空格，要保证数据的一致性，否则%Y-%m-%d %H:%i:%s就不对了 @author lh_neu
		String replaceStr = str;
		if (StringUtils.isNotEmpty(replaceStr)) {
			// 因为 \ 比较特殊，单个的时候表示转义字符，必须成对出现。所以首先判断str有连续的几个\，若单数的则添加成双数
			final StringBuffer all = new StringBuffer("");
			final StringBuffer s = new StringBuffer("");
			for (int i = 0; i < replaceStr.length(); i++) {
				switch (replaceStr.charAt(i)) {
					case '\\':
						s.append(replaceStr.charAt(i));
						break;
					default:
						// 判断是否连续的偶数个
						if (StringUtils.isNotEmpty(s.toString())) {
							if (s.toString().length() % 2 != 0) {
								s.append('\\');
							}
							all.append(s.toString());
							s.delete(0, s.length());
						}
						all.append(replaceStr.charAt(i));
						break;
				}
			}
			replaceStr = all.toString();

			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				replaceStr = replaceStr.replaceAll(StringConstants.STRING_SPLIT_FLAG_4,
						SQLUtil.getConnector(dbType, "' ", SQLUtil.getConnector(dbType, "chr(39)", " '")));
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				replaceStr = replaceStr.replaceAll(StringConstants.STRING_SPLIT_FLAG_4,
						SQLUtil.getConnector(dbType, "' ", SQLUtil.getConnector(dbType, "char(39)", " '")));
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				final Pattern pattern = Pattern.compile("'");
				final Matcher matcher = pattern.matcher(replaceStr);
				replaceStr = matcher.replaceAll("\\\\'");
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				final Pattern pattern = Pattern.compile("'");
				final Matcher matcher = pattern.matcher(replaceStr);
				replaceStr = matcher.replaceAll("\\\\'");
			}
		}
		return replaceStr;
	}

	/**
	 * 将值替换特殊字符
	 *
	 * @param value
	 *            原值
	 * @return 转换后的值
	 */
	public static Object replaceStrObject(final Object value) {
		return SQLUtil.replaceStrObject(SQLUtil.dbType, value);
	}

	/**
	 * 将值替换特殊字符
	 *
	 * @param dbType
	 *            数据库类型
	 * @param value
	 *            原值
	 * @return 转换后的值
	 */
	public static Object replaceStrObject(final String dbType, final Object value) {
		Object result = "";
		if (value != null) {
			if (value instanceof java.lang.String) {
				result = SQLUtil.replaceStr(dbType, (String) value);
			} else if (value instanceof java.math.BigDecimal) {
				result = new java.math.BigDecimal(0);
			}
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 将多个值替换特殊字符
	 * <p>
	 * 将字符串中的单引号根据数据库类型进行相应替换
	 *
	 * @author lh_neu
	 * @param values
	 *            多个原值
	 */
	public static Map<String, Object> replaceMapValues(final Map<String, Object> values) {
		return SQLUtil.replaceMapValues(SQLUtil.dbType, values);
	}

	/**
	 * 将多个值替换特殊字符
	 * <p>
	 * 将字符串中的单引号根据数据库类型进行相应替换
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param values
	 *            多个原值
	 */
	public static Map<String, Object> replaceMapValues(final String dbType, final Map<String, Object> values) {
		if (values != null) {
			final Iterator<Map.Entry<String, Object>> iter = values.entrySet().iterator();
			while (iter.hasNext()) {
				final Map.Entry<String, Object> entry = iter.next();
				final String key = entry.getKey();
				Object value = entry.getValue();
				if (value instanceof java.lang.String) {
					value = SQLUtil.replaceStr(dbType, (String) value);
				} else if (value instanceof java.math.BigDecimal) {
					value = new java.math.BigDecimal(0);
				} else {
					value = "";
				}
				values.put(key, value);
			}
		}
		return values;
	}

	/**
	 * 获取连词符
	 * <p>
	 * 将两个字符串根据数据库类型进行相连。例如：
	 * <p>
	 * Input -> str1 = 'chinact' , str2 = 'ctd'
	 * <p>
	 * Output -> 'chinact' || 'ctd'
	 *
	 * @author lh_neu
	 * @param str1
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @param str2
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @return 连接后的字符串，不带左右单引号
	 */
	public static String getConnector(final String str1, final String str2) {
		return SQLUtil.getConnector(SQLUtil.dbType, str1, str2);
	}

	/**
	 * 获取连词符
	 * <p>
	 * 将两个字符串根据数据库类型进行相连。例如：
	 * <p>
	 * Input -> str1 = 'chinact' , str2 = 'ctd'
	 * <p>
	 * Output -> 'chinact' || 'ctd'
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param str1
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @param str2
	 *            HQL中的列、HQL参数或左右带单引号的字符
	 * @return 连接后的字符串，不带左右单引号
	 */
	public static String getConnector(final String dbType, final String str1, final String str2) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = str1 + " || " + str2;
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = str1 + " + " + str2;
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "CONCAT(" + str1 + "," + str2 + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "CONCAT(" + str1 + "," + str2 + ")";
		}
		return result;
	}

	/**
	 * 科学计数格式化数字，而且可以根据条件四舍五入
	 *
	 * @param str1
	 *            待转换的数字
	 * @param str2
	 *            位数
	 * @return 连接后的字符串
	 */
	public static String round(final String str1, final int str2) {
		return SQLUtil.round(SQLUtil.dbType, str1, str2);
	}

	/**
	 * 科学计数格式化数字，而且可以根据条件四舍五入
	 *
	 * @param dbType
	 *            数据库类型
	 * @param str1
	 *            待转换的数字
	 * @param str2
	 *            位数
	 * @return 连接后的字符串
	 */
	public static String round(final String dbType, final String str1, final int str2) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = "ROUND(" + str1 + ", " + str2 + ")";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = "ROUND(" + str1 + ", " + str2 + ")";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "FORMAT(" + str1 + ", " + str2 + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "FORMAT(" + str1 + ", " + str2 + ")";
		}
		return result;
	}

	/**
	 * 获取某日期的小时
	 *
	 * @param date
	 *            日期字段
	 * @return 小时
	 */
	public static String hour(final String date) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
			result = "TO_CHAR(" + date + ",'hh24')";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
			result = "DATEPART(hh," + date + ")";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
			result = "hour(" + date + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
			result = "hour(" + date + ")";
		}
		return result;
	}

	/**
	 * 获取某日期是一年中的第几周
	 *
	 * @param date
	 *            日期字段
	 * @return 一年中的第几周
	 */
	public static String week(final String date) {
		return SQLUtil.week(SQLUtil.dbType, date);
	}

	/**
	 * 获取某日期是一年中的第几周
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            日期字段
	 * @return 一年中的第几周
	 */
	public static String week(final String dbType, final String date) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = "TO_CHAR(" + date + ",'ww')";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = "DATENAME(week," + date + ")";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "WEEK(" + date + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "WEEK(" + date + ")";
		}
		return result;
	}

	/**
	 * 获取某日期是一年中的几月
	 *
	 * @param date
	 *            日期字段
	 * @return 一年中的几月
	 */
	public static String month(final String date) {
		return SQLUtil.month(SQLUtil.dbType, date);
	}

	/**
	 * 获取某日期是一年中的几月
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            日期字段
	 * @return 一年中的几月
	 */
	public static String month(final String dbType, final String date) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = "to_char(" + date + ",'MM')";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = "DATENAME(month," + date + ")";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "MONTH(" + date + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "MONTH(" + date + ")";
		}
		return result;
	}

	/**
	 * 获取某日期年份
	 *
	 * @param date
	 *            日期字段
	 * @return 年份
	 */
	public static String year(final String date) {
		return SQLUtil.year(SQLUtil.dbType, date);
	}

	/**
	 * 获取某日期年份
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            日期字段
	 * @return 年份
	 */
	public static String year(final String dbType, final String date) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = "to_char(" + date + ",'yyyy')";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = "DATENAME(year," + date + ")";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "YEAR(" + date + ")";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "YEAR(" + date + ")";
		}
		return result;
	}

	/**
	 * 获取系统时间
	 * <p>
	 * Output -> SYSDATE
	 * <p>
	 * Output -> sysdate()
	 * <p>
	 * Output -> getdate()
	 *
	 * @return 系统时间
	 */
	public static String getDefaultDate() {
		return SQLUtil.getDefaultDate(SQLUtil.dbType);
	}

	/**
	 * 获取系统时间
	 * <p>
	 * Output -> SYSDATE
	 * <p>
	 * Output -> sysdate()
	 * <p>
	 * Output -> getdate()
	 *
	 * @param dbType
	 *            数据库类型
	 * @return 系统时间
	 */
	public static String getDefaultDate(final String dbType) {
		String result = "";
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
			result = "SYSDATE";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
			result = "sysdate()";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
			result = "sysdate()";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
			result = "getdate()";
		}
		return result;
	}

	/**
	 * 获取触发器标识：存储insert的记录
	 * <p>
	 * Output -> :new.
	 *
	 * @return 标识
	 */
	public static String getTriggerNewSplit() {
		String result = "";
		if (SQLUtil.isOracle()) {
			result = TriggerUtil.TRI_NEW_ORACLE;
		} else if (SQLUtil.isMySQL()) {
			result = TriggerUtil.TRI_NEW_MYSQL;
		} else if (SQLUtil.isSQLServer()) {
			result = TriggerUtil.TRI_NEW_SQLSERVER;
		}
		return result;
	}

	/**
	 * 获取触发器标识：存储delete ,update的记录
	 * <p>
	 * Output -> :old.
	 *
	 * @return 标识
	 */
	public static String getTriggerOldSplit() {
		String result = "";
		if (SQLUtil.isOracle()) {
			result = TriggerUtil.TRI_OLD_ORACLE;
		} else if (SQLUtil.isMySQL()) {
			result = TriggerUtil.TRI_OLD_MYSQL;
		} else if (SQLUtil.isSQLServer()) {
			result = TriggerUtil.TRI_OLD_SQLSERVER;
		}
		return result;
	}

	/**
	 * 如果str1 的计算结果为 null值，则 NVL( ) 返回 str2
	 * <p>
	 * 注意，两个值并没有做特殊字符处理。例如：
	 * <p>
	 * Input -> str1 = 'chinact' , str2 = 'ctd'
	 * <p>
	 * Output -> NVL ('chinact', 'ctd')
	 *
	 * @author lh_neu
	 * @param str1
	 *            判断的值。HQL中的列、HQL参数或左右带单引号的字符
	 * @param str2
	 *            默认值。HQL中的列、HQL参数或左右带单引号的字符
	 * @return 转换后的语句
	 */
	public static String nvl(final String str1, final String str2) {
		String result = "";
		if (StringUtils.isNotEmpty(str1) && (str2 != null)) { // str2 可以为空串
			if (SQLUtil.isOracle()) {
				result = "NVL(" + str1 + ", " + str2 + ")";
			} else if (SQLUtil.isMySQL()) {
				result = "IFNULL(" + str1 + ", " + str2 + ")";
			} else if (SQLUtil.isSQLServer()) {
				result = "ISNULL(" + str1 + ", " + str2 + ")";
			}
		}
		return result;
	}

	/**
	 * 字符串转换为日期函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_DATE('2011-05-26 11:32:12','yyyy-mm-dd')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_DATE(model.beginTime,'yyyy-mm-dd')
	 *
	 * @author lh_neu
	 * @param str
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd 格式日期
	 */
	public static String strToDate(final String str) {
		return SQLUtil.strToDate(SQLUtil.dbType, str);
	}

	/**
	 * 字符串转换为日期函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_DATE('2011-05-26 11:32:12','yyyy-mm-dd')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_DATE(model.beginTime,'yyyy-mm-dd')
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param str
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd 格式日期
	 */
	public static String strToDate(final String dbType, final String str) {
		String result = "";
		if (StringUtils.isNotEmpty(str)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_DATE(" + str + ",'yyyy-mm-dd')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "cast(" + str + " as datetime)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "STR_TO_DATE(" + str + ",'%Y-%m-%d')";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "STR_TO_DATE(" + str + ",'%Y-%m-%d')";
			}
		}
		return result;
	}

	/**
	 * 字符串转换为日期函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_DATE('2011-05-26 11:32:12','yyyy-mm-dd hh24:mi:ss')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_DATE(model.beginTime,'yyyy-mm-dd hh24:mi:ss')
	 *
	 * @author lh_neu
	 * @param str
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd hh24:mi:ss 格式日期
	 */
	public static String strToDateTime(final String str) {
		return SQLUtil.strToDateTime(SQLUtil.dbType, str);
	}

	/**
	 * 字符串转换为日期函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_DATE('2011-05-26 11:32:12','yyyy-mm-dd hh24:mi:ss')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_DATE(model.beginTime,'yyyy-mm-dd hh24:mi:ss')
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param str
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd hh24:mi:ss 格式日期
	 */
	public static String strToDateTime(final String dbType, final String str) {
		String result = "";
		if (StringUtils.isNotEmpty(str)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_DATE(" + str + ",'yyyy-mm-dd hh24:mi:ss')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "cast(" + str + " as datetime)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "STR_TO_DATE(" + str + ",'%Y-%m-%d %H:%i:%s')";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "STR_TO_DATE(" + str + ",'%Y-%m-%d %H:%i:%s')";
			}
		}
		return result;
	}

	/**
	 * 取两个日期之间的相差的月份
	 * <p>
	 * Input -> '2011-07-26','2011-05-26'
	 * <p>
	 * Output -> 2
	 *
	 * @param date1
	 *            日期1
	 * @param date2
	 *            日期2，一定早于data1
	 * @return 返回月份格式的字符串
	 */
	public static String monthsBetween(final String date1, final String date2) {
		return SQLUtil.monthsBetween(SQLUtil.dbType, date1, date2);
	}

	/**
	 * 取两个日期之间的相差的月份
	 * <p>
	 * Input -> '2011-07-26','2011-05-26'
	 * <p>
	 * Output -> 2
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date1
	 *            日期1
	 * @param date2
	 *            日期2，一定早于data1
	 * @return 返回月份格式的字符串
	 */
	public static String monthsBetween(final String dbType, final String date1, final String date2) {
		String result = "";
		if (StringUtils.isNotEmpty(date1) && StringUtils.isNotEmpty(date2)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "months_between(" + date1 + "," + date2 + ")";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "DATEDIFF(mm, " + date1 + "," + date2 + ")";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "TIMESTAMPDIFF(MONTH, " + date1 + "," + date2 + ")";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "TIMESTAMPDIFF(MONTH, " + date1 + "," + date2 + ")";
			}
		}
		return result;
	}

	/**
	 * 日期转换为字符串函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_CHAR ('2011-05-26 11:32:12', 'yyyy-mm-dd')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_CHAR(model.beginTime, 'yyyy-mm-dd')
	 *
	 * @author lh_neu
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd格式的字符串
	 */
	public static String dateToStr(final String date) {
		return SQLUtil.dateToStr(SQLUtil.dbType, date);
	}

	/**
	 * 日期转换为字符串函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_CHAR ('2011-05-26 11:32:12', 'yyyy-mm-dd')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_CHAR(model.beginTime, 'yyyy-mm-dd')
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd格式的字符串
	 */
	public static String dateToStr(final String dbType, final String date) {
		String result = "";
		if (StringUtils.isNotEmpty(date)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_CHAR (" + date + ", 'yyyy-mm-dd')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "CONVERT(varchar(10), " + date + ", 23)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m-%d')";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m-%d')";
			}
		}
		return result;
	}

	/**
	 * 日期转换为yyyy-mm格式的字符串函数
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> DATE_FORMAT('2011-05-26 11:32:12','%Y-%m')
	 * <p>
	 *
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd格式的字符串
	 */
	public static String dateToStrByYearAndMonth(final String date) {
		return SQLUtil.dateToStrByYearAndMonth(SQLUtil.dbType, date);
	}

	/**
	 * 日期转换为yyyy-mm格式的字符串函数
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd格式的字符串
	 */
	public static String dateToStrByYearAndMonth(final String dbType, final String date) {
		String result = "";
		if (StringUtils.isNotEmpty(date)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_CHAR (" + date + ", 'yyyy-mm')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "CONVERT(varchar(7), " + date + ", 120)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m')";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m')";
			}
		}
		return result;
	}

	/**
	 * 获取一个日期是本年的第几周。例如：
	 * <p>
	 * Input -> '2011-01-01'
	 * <p>
	 * Output -> 1
	 *
	 * @param date
	 *            日期，yyyy-mm-dd格式的
	 * @return 第一周的SQL
	 */
	public static String getWeekOfYear(final String date) {
		return SQLUtil.getWeekOfYear(SQLUtil.dbType, date);
	}

	/**
	 * 获取一个日期是本年的第几周
	 *
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            日期，yyyy-mm-dd格式的
	 * @return 第一周的SQL
	 */
	public static String getWeekOfYear(final String dbType, final String date) {
		String result = "";
		if (StringUtils.isNotEmpty(date)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_CHAR (" + date + ", 'WW')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "datepart(wk," + date + ")";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "YEARWEEK(DATE_FORMAT(" + date + ",'%Y-%m-%d'))";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "YEARWEEK(DATE_FORMAT(" + date + ",'%Y-%m-%d'))";
			}
		}
		return result;
	}

	/**
	 * 字符串转换数字
	 *
	 * @param str
	 *            字符串
	 * @return 返回数字格式的字符串
	 */
	public static String strToNum(final String str) {
		return SQLUtil.strToNum(SQLUtil.dbType, str);
	}

	/**
	 * 字符串转换数字
	 *
	 * @param dbType
	 *            数据库类型
	 * @param str
	 *            字符串
	 * @return 返回数字格式的字符串
	 */
	public static String strToNum(final String dbType, final String str) {
		String result = "";
		if (StringUtils.isNotEmpty(str)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "CAST(" + str + " AS NUMBER)";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "CAST(" + str + " AS SIGNED)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "CAST(" + str + " AS SIGNED)";
			}
		}
		return result;
	}

	/**
	 * 字段中某个字符串替换
	 *
	 * @param field
	 *            列
	 * @param oldInfo
	 *            原数据
	 * @param newInfo
	 *            新数据
	 * @return 返回替换格式的字符串
	 */
	public static String replace(final String field, final String oldInfo, final String newInfo) {
		return SQLUtil.replace(SQLUtil.dbType, field, oldInfo, newInfo);
	}

	/**
	 * 字段中某个字符串替换
	 *
	 * @param dbType
	 *            数据库类型
	 * @param field
	 *            列
	 * @param oldInfo
	 *            原数据
	 * @param newInfo
	 *            新数据
	 * @return 返回替换格式的字符串
	 */
	public static String replace(final String dbType, final String field, final String oldInfo, final String newInfo) {
		String result = "";
		if (StringUtils.isNotEmpty(field)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "REPLACE(" + field + ",\"" + oldInfo + "\",\"" + newInfo + "\")";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "REPLACE(" + field + ",\"" + oldInfo + "\",\"" + newInfo + "\")";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "REPLACE(" + field + ",\"" + oldInfo + "\",\"" + newInfo + "\")";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "REPLACE(" + field + ",\"" + oldInfo + "\",\"" + newInfo + "\")";
			}
		}
		return result;
	}

	/**
	 * 日期转换为字符串函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_CHAR ('2011-05-26 11:32:12', 'yyyy-mm-dd hh24:mi:ss')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_CHAR(model.beginTime, 'yyyy-mm-dd hh24:mi:ss')
	 *
	 * @author lh_neu
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd hh24:mi:ss 格式的字符串
	 */
	public static String dateTimeToStr(final String date) {
		return SQLUtil.dateTimeToStr(SQLUtil.dbType, date);
	}

	/**
	 * 日期转换为字符串函数
	 * <p>
	 * 注意，参数没有做特殊字符处理。例如：
	 * <p>
	 * Input -> '2011-05-26 11:32:12'
	 * <p>
	 * Output -> TO_CHAR ('2011-05-26 11:32:12', 'yyyy-mm-dd hh24:mi:ss')
	 * <p>
	 * 再如在Hibernate中可以这样输入：
	 * <p>
	 * Input -> model.beginTime
	 * <p>
	 * Output -> TO_CHAR(model.beginTime, 'yyyy-mm-dd hh24:mi:ss')
	 *
	 * @author lh_neu
	 * @param dbType
	 *            数据库类型
	 * @param date
	 *            HQL中的列、HQL参数或字符串
	 * @return 返回 yyyy-mm-dd hh24:mi:ss 格式的字符串
	 */
	public static String dateTimeToStr(final String dbType, final String date) {
		String result = "";
		if (StringUtils.isNotEmpty(date)) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(dbType)) {
				result = "TO_CHAR (" + date + ", 'yyyy-mm-dd hh24:mi:ss')";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(dbType)) {
				result = "CONVERT(varchar(100), " + date + ", 120)";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m-%d %H:%i:%s')";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(dbType)) {
				result = "DATE_FORMAT(" + date + ",'%Y-%m-%d %H:%i:%s')";
			}
		}
		return result;
	}

	/**
	 * 拼接查询使用sql 若查询条件中有‘'’单引号，则要用||chr(39)||进行转换
	 * <p>
	 * 例1：绝对查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name = '你' ||chr(39)|| '好'
	 * <p>
	 * 例2：模糊查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("isLike", true);property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name like '%你' ||chr(39)|| '好%'
	 *
	 * @author lh_neu
	 * @param split
	 *            AND/OR
	 * @param hql
	 *            sql语句前半部分
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询。参数传递后，进行特殊字符处理
	 * @return 拼接后的sql
	 */
	public static StringBuffer createSql(final String split, final StringBuffer hql,
			final Map<String, Object> property) {
		return SQLUtil.createSql(split, hql, property, "model");
	}

	/**
	 * 拼接查询使用sql 若查询条件中有‘'’单引号，则要用||chr(39)||进行转换
	 * <p>
	 * 例1：绝对查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name = '你' ||chr(39)|| '好'
	 * <p>
	 * 例2：模糊查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("isLike", true);property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name like '%你' ||chr(39)|| '好%'
	 *
	 * @author lh_neu
	 * @param hql
	 *            sql语句前半部分
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询。参数传递后，进行特殊字符处理
	 * @return 拼接后的sql
	 */
	public static StringBuffer createSql(final StringBuffer hql, final Map<String, Object> property) {
		return SQLUtil.createSql(hql, property, "model");
	}

	/**
	 * 拼接查询使用sql 若查询条件中有‘'’单引号，则要用||chr(39)||进行转换
	 * <p>
	 * 例1：绝对查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name = '你' ||chr(39)|| '好'
	 * <p>
	 * 例2：模糊查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("isLike", true);property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name like '%你' ||chr(39)|| '好%'
	 *
	 * @author lh_neu
	 * @param hql
	 *            sql语句前半部分
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询。参数传递后，进行特殊字符处理
	 * @param model
	 *            model
	 * @return 拼接后的sql
	 */
	public static StringBuffer createSql(final StringBuffer hql, final Map<String, Object> property,
			final String model) {
		return SQLUtil.createSql("AND", hql, property, model);
	}

	/**
	 * 拼接查询使用sql 若查询条件中有‘'’单引号，则要用||chr(39)||进行转换
	 * <p>
	 * 例1：绝对查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name = '你' ||chr(39)|| '好'
	 * <p>
	 * 例2：模糊查询
	 * <p>
	 * Input -> sql = "from UserObj as model where 1=1" , property.put("isLike", true);property.put("name", "你'好");
	 * <p>
	 * Output -> from UserObj as model where 1=1 and model.name like '%你' ||chr(39)|| '好%'
	 *
	 * @author lh_neu
	 * @param split
	 *            AND/OR
	 * @param hql
	 *            sql语句前半部分
	 * @param property
	 *            参数。其中isLike:Boolean 是否模糊查询。参数传递后，进行特殊字符处理
	 * @param model
	 *            model
	 * @return 拼接后的sql
	 */
	@SuppressWarnings("rawtypes")
	public static StringBuffer createSql(String split, final StringBuffer hql, final Map<String, Object> property,
			final String model) {
		if (property != null) {
			if (StringUtils.isEmpty(split)) {
				split = "AND";
			}
			// 是否模糊查询
			Boolean isLike = (Boolean) property.get("isLike");
			if (isLike == null) {
				isLike = false;
			}
			final Iterator<?> iter = property.entrySet().iterator();
			while (iter.hasNext()) {
				final Map.Entry entry = (Map.Entry) iter.next();
				String key = (String) entry.getKey();
				if (!"isLike".equals(key)) {
					if (StringUtils.indexOfIgnoreCase(key, model + ".") < 0) {
						key = model + "." + key;
					}

					final Object obj = entry.getValue();
					if (obj instanceof String) {
						final String value = (String) obj;
						if (StringUtils.isNotEmpty(value)) {
							hql.append(" " + split + " " + key + " " + SQLUtil.likeOrEquale(isLike, value));
						}
					} else if (obj instanceof Long) {
						final Long value = (Long) obj;
						hql.append(" " + split + " " + key + " = " + value.longValue());
					} else if (obj instanceof Integer) {
						final Integer value = (Integer) obj;
						hql.append(" " + split + " " + key + " = " + value.intValue());
					} else {
						hql.append(" " + split + " " + key + " = " + obj);
					}
				}
			}
		}
		return hql;
	}

	/**
	 * 根据是否模糊查询拼接参数。例如：
	 * <p>
	 * Input -> true , chinact'ctd
	 * <p>
	 * Output -> like '%chinact' ||chr(39)|| 'ctd%'
	 *
	 * @param isLike
	 *            是否模糊
	 * @param param
	 *            参数。参数传递后，进行特殊字符处理
	 * @return sql
	 */
	public static String likeOrEquale(final boolean isLike, final String param) {
		final String replaceStr = SQLUtil.replaceStr(param);
		if (StringUtils.isNotEmpty(replaceStr)) {
			if (isLike) {
				if (replaceStr.equals("%")) {
					final String escape = "/";
					return " like '%/" + replaceStr + "%' escape '" + escape + "'";
				} else {
					return " like '%" + replaceStr + "%' ";
				}

			} else {
				return " = '" + replaceStr + "' ";
			}
		} else {
			return "";
		}
	}

	/**
	 * Get page query
	 * <p>
	 * sql = SQLUtilss.getRowCode(sql);
	 * <p>
	 * sql = sql.replaceAll(":start", String.valueOf(start));
	 * <p>
	 * sql = sql.replaceAll(":end-start", String.valueOf(countNum));
	 * <p>
	 * sql = sql.replaceAll(":end", String.valueOf(end));
	 *
	 * @param sql
	 *            sql statement
	 * @return 分页查询语句 :end 结束数，:start 开始数, :end-start 每页的记录数
	 */
	public static String getRowCode(String sql) {
		if (SQLUtil.isOracle()) {
			if ((sql.indexOf("group by") < 0) && (sql.indexOf("GROUP BY") < 0) && (sql.indexOf("order by") < 0)
					&& (sql.indexOf("ORDER BY") < 0)) {
				sql = sql.replaceFirst("FROM", ",ROWNUM num FROM");
				sql = sql.replaceFirst("from", ",ROWNUM num from");
				sql = "SELECT * FROM( " + sql;
				sql = sql + ") WHERE num <=:end AND num >:start";
			} else {
				return "SELECT * FROM ( SELECT row_.* FROM (select trow_.*,ROWNUM rownum_ FROM(" + sql
						+ ") trow_) row_  WHERE rownum <= :end)   WHERE rownum_ > :start";
			}
		} else if (SQLUtil.isSQLServer()) {

			// SQLServer 分页方法：select * from (select top 页面容量 * from (select top 页面容量*当前页码 * from 表  where 条件 order by 字段A) as temptable1 order by 字段A desc ) as temptable2 order by 字段A
			// 例如：select * from (select top 5 * from (select top 15 * from TEST order by name desc) as temptable1 order by name asc ) as temptable2 order by name desc

			// 基于以上方式，需要对SQL语句进行截取，即截取原有的order by，在分页的temptable1语句中，需要根据指定的排序进行反排序方可实现该功能
			sql = StringUtils.trimToEmpty(sql);

			// 这里必须去掉sql中的第一个select
			if (StringUtils.indexOfIgnoreCase(sql, "SELECT") == 0) {
				sql = StringUtils.substring(sql, "SELECT".length());
			}

			if (StringUtils.indexOfIgnoreCase(sql, "ORDER BY") >= 0) {
				// String sqlBefore = StringUtils.substring(sql, 0, StringUtil.ignoreIndexOf(sql, "ORDER BY"));
				String order = StringUtils.substring(sql, StringUtils.indexOfIgnoreCase(sql, "ORDER BY"));

				// 将排序反转过来
				String reOrder = order.replaceAll("DESC", "ORDER_D");
				reOrder = reOrder.replaceAll("ASC", "ORDER_A");
				reOrder = reOrder.replaceAll("desc", "ORDER_D");
				reOrder = reOrder.replaceAll("asc", "ORDER_A");

				// 统一将别名修改为model.
				reOrder = StringUtil.substringAfterIgnoreCase(reOrder, "ORDER BY");
				String[] fields = StringUtil.str2Arr(reOrder);
				if (fields != null && fields.length >= 0) {
					for (final String field : fields) {
						final String[] temps = StringUtil.str2Arr(field, ".");
						if (temps != null && temps.length >= 2) {
							reOrder = reOrder.replaceAll(temps[0] + ".", "model.");
						}
					}
				}
				reOrder = " ORDER BY " + reOrder;
				order = StringUtil.substringAfterIgnoreCase(order, "ORDER BY");
				fields = StringUtil.str2Arr(order);
				if (fields != null && fields.length >= 0) {
					for (final String field : fields) {
						final String[] temps = StringUtil.str2Arr(field, ".");
						if (temps != null && temps.length >= 2) {
							order = order.replaceAll(temps[0] + ".", "model.");
						}
					}
				}
				order = " ORDER BY " + order;

				// 将数据库字段转换为对象属性
				fields = StringUtils.substringsBetween(reOrder, "model.", " ORDER_");
				if (fields != null && fields.length >= 0) {
					for (final String field : fields) {
						reOrder = reOrder.replaceAll(field, TableUtil.columnToField(field));
						order = order.replaceAll(field, TableUtil.columnToField(field));
					}
				}

				reOrder = reOrder.replaceAll("ORDER_D", "ASC");
				reOrder = reOrder.replaceAll("ORDER_A", "DESC");

				return "SELECT * FROM (SELECT TOP :end-start * FROM (SELECT TOP :end " + sql + " ) AS ASYSTABLE "
						+ reOrder.replaceAll("model.", "") + ") AS BSYSTABLE " + order.replaceAll("model.", "");
			} else {
				return "SELECT * FROM (SELECT TOP :end-start * FROM (SELECT TOP :end " + sql
						+ " ) AS ASYSTABLE) AS BSYSTABLE";
			}

		} else if (SQLUtil.isMySQL()) {
			return sql + " limit :start,:end-start";
		}
		return sql;
	}

	/**
	 * 替换SQL中的特殊字符
	 * <p>
	 * 例如：WHERE model.USER_NAME like '%姓'名%' And model.USER_LOGIN like '%姓'名'，需要处理单引号
	 *
	 * @param sql
	 *            SQL
	 * @return SQL
	 */
	public static String replaceWhereLikeSQL(String sql) {
		if (StringUtils.isEmpty(sql)) {
			return sql;
		}
		final String split = "%";
		if (sql.indexOf(split) <= -1) {
			return sql;
		}
		final StringBuffer sb = new StringBuffer("");
		int index = 0;
		// 搜索标签开始位置
		while ((index = sql.indexOf(split)) != -1) {
			// 拼接文本中第一个标签之前的内容
			sb.append(sql.substring(0, index));

			// 找出标签结束位置
			final int endIndex = sql.indexOf(split, index + split.length());
			if (endIndex <= -1) {
				sql = sql.substring(index);
				break;
			}
			final String tag = sql.substring(index, endIndex + split.length());
			// 待替换的内容
			String replactStr = StringUtils.substringBetween(tag, split, split);

			// 判断是否包括or或者and，若有，则说明是两个查询条件（半边模糊），不做处理
			if (StringUtils.indexOf(replactStr.toUpperCase(), " OR ") >= 0
					|| StringUtils.indexOf(replactStr.toUpperCase(), " AND ") >= 0) {
				sql = sql.substring(index);
				break;
			}

			// 从原文本中去掉已替换的标签内容
			sql = sql.substring(index + tag.length());

			// 替换后的内容
			replactStr = SQLUtil.replaceStr(replactStr);

			// 将处理后的标签拼接到结果集中
			sb.append(split + replactStr + split);

		}
		return sb.toString() + sql;
	}

	/**
	 * 获取分页QL语句
	 *
	 * @param offset
	 *            当前页数：从0开始
	 * @param limit
	 *            分页长度
	 * @param sql
	 *            SQL语句
	 * @return 分页的 SQL语句
	 */
	public static String getPageSQL(final int offset, final int limit, final String sql) {
		return SQLUtil.getPageSQL(offset, limit, -1, sql);
	}

	/**
	 * 获取分页QL语句
	 *
	 * @param offset
	 *            当前页数：从0开始
	 * @param limit
	 *            分页长度
	 * @param count
	 *            总记录数，是给SQLServer专门用的
	 * @param sql
	 *            SQL语句
	 * @return 分页的 SQL语句
	 */
	public static String getPageSQL(final int offset, int limit, final int count, String sql) {
		// offset从0开始的
		final int start = offset * limit;
		final int end = (offset + 1) * limit;
		// offset从1开始的
		//		int start = (offset - 1) * limit;
		//		int end = offset * limit;
		if ((start < 0) || (start > end)) {
			return null;
		}
		//		final String contsql = "SELECT COUNT(*) FROM (" + sql + ") M";
		//
		//		if (SQLUtils.isShowSql()) {
		//			Log.error(contsql);
		//		}
		//		int limits = 0;
		//		try {
		//			limits = jdbcTemplate.queryForObject(contsql, Integer.class);
		//		} catch (Exception e) {
		//		}
		//		if (end > limits) {
		//			end = limits;
		//		}
		sql = SQLUtil.getRowCode(sql);
		sql = sql.replaceAll(":start", String.valueOf(start));

		// 对于SQLServer数据库来说，最后一页的:end-start应该是end-count，也就是if(count<end):end-start=end-count
		if (count > 0 && SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.getDbType())) {
			if (count < end) {
				limit = count - start;
			}
		}
		sql = sql.replaceAll(":end-start", String.valueOf(limit));
		sql = sql.replaceAll(":end", String.valueOf(end));

		return sql;
	}

	/**
	 * 读oracle BLOB类型
	 *
	 * @param vField
	 *            大字段
	 * @param vSize
	 *            字段长度
	 * @return 值
	 * @throws SQLException
	 *             Exception
	 * @throws IOException
	 *             Exception
	 */
	public static String getBlob(final java.sql.Blob vField, final int vSize) throws SQLException, IOException {
		String mSignData = null;
		InputStream instream = null;
		try {
			final byte[] mTmp = new byte[vSize];
			instream = vField.getBinaryStream();
			instream.read(mTmp, 0, vSize);
			mSignData = new String(mTmp);
			mSignData = null;
		} catch (final IOException e) {
			Log.error(e.getMessage());
		} finally {
			if (instream != null) {
				instream.close();
			}
		}
		return (mSignData);
	}

	/**
	 * 数据库类型转换java类型
	 *
	 * @param dataType
	 *            数据库类型
	 * @return JAVA类型
	 */
	public static String dbFieldToJava(final String dataType) {
		if (StringUtils.isEmpty(dataType)) {
			return "";
		}
		boolean isInt = false;
		boolean isLong = false;
		boolean isFloat = false;
		boolean isDouble = false;
		boolean isDate = false;
		// TODO 这个地方用以个配置文件，配置数据库类型对对象类型的关联
		if (dataType.trim().equalsIgnoreCase("INT") || dataType.trim().equalsIgnoreCase("LONG")
				|| dataType.trim().equalsIgnoreCase("INTEGER") || dataType.trim().equalsIgnoreCase("TINYINT")) {
			isInt = true;
		} else if (dataType.trim().equalsIgnoreCase("FLOAT") || dataType.trim().equalsIgnoreCase("REAL")) {
			isFloat = true;
		} else if (dataType.trim().equalsIgnoreCase("DOUBLE") || dataType.trim().equalsIgnoreCase("DECIMAL")
				|| dataType.trim().equalsIgnoreCase("NUMBER") || dataType.trim().equalsIgnoreCase("NUMBER")) {
			isDouble = true;
		} else if (dataType.trim().equalsIgnoreCase("DATETIME") || dataType.trim().equalsIgnoreCase("DATE")
				|| dataType.trim().equalsIgnoreCase("TIME")) {
			isDate = true;
		} else if (dataType.trim().equalsIgnoreCase("BIGINT")) {
			isLong = true;
		}
		if (isFloat) {
			return "float";
		}
		if (isDouble) {
			return "double";
		}
		if (isDate) {
			return "LocalDateTime";
		}
		if (isLong) {
			return "long";
		}
		if (isInt) {
			return "int";
		}

		return "String";
	}

	/**
	 * java类型转换数据库类型
	 *
	 * @param javaType
	 *            java类型
	 * @return 数据库类型
	 */
	public static String javaFieldToDB(final String javaType) {
		if (StringUtils.isEmpty(javaType)) {
			return "";
		}
		boolean isInt = false;
		boolean isFloat = false;
		boolean isDouble = false;
		boolean isDate = false;
		// TODO 这个地方用以个配置文件，配置数据库类型对对象类型的关联
		if (javaType.trim().equalsIgnoreCase("int") || javaType.trim().equalsIgnoreCase("Integer")) {
			isInt = true;
		} else if (javaType.trim().equalsIgnoreCase("FLOAT")) {
			isFloat = true;
		} else if (javaType.trim().equalsIgnoreCase("DOUBLE")) {
			isDouble = true;
		} else if (javaType.trim().equalsIgnoreCase("DATETIME") || javaType.trim().equalsIgnoreCase("DATE")) {
			isDate = true;
		}
		if (isFloat) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "NUMBER";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
				return "FLOAT";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
				return "FLOAT";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "FLOAT";
			}
		}
		if (isDouble) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "NUMBER";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
				return "NUMERIC";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DOUBLE";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DOUBLE";
			}
		}
		if (isDate) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DATE";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DATETIME";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DATETIME";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "DATETIME";
			}
		}
		if (isInt) {
			if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "NUMBER";
			} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
				return "INT";
			} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
				return "INT";
			} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
				return "INT";
			}
		}

		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
			return "NVARCHAR2";
		} else if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
			return "VARCHAR";
		} else if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
			return "VARCHAR";
		} else if (SQLUtil.DB_GBASE.equalsIgnoreCase(SQLUtil.dbType)) {
			return "VARCHAR";
		}
		return "";
	}

	//	/**
	//	 * oracle 写BLOB类型
	//	 *
	//	 * @param vField
	//	 *            大字段
	//	 * @param SignatureBody
	//	 *            值
	//	 * @throws IOException
	//	 *             Exception
	//	 */
	//	@SuppressWarnings("deprecation")
	//	public static void setBlob(final BLOB vField, final byte[] SignatureBody) throws IOException {
	//		OutputStream outstream = null;
	//		try {
	//			final int vSize = SignatureBody.length;
	//			outstream = vField.getBinaryOutputStream();
	//			outstream.write(SignatureBody, 0, vSize);
	//			outstream.flush();
	//		} catch (final SQLException e) {
	//			Log.error(e.getMessage());
	//		} finally {
	//			if (outstream != null) {
	//				outstream.close();
	//			}
	//		}
	//	}

	/**
	 * 数据库字段转为对象属性
	 * <p>
	 * 首字母小写，后词组首字母大写
	 *
	 * @param columnName
	 *            字段名称
	 * @return 属性名称
	 */
	public static String columnToField(String columnName) {
		// 全部转换为小写
		columnName = StringUtils.trimToEmpty(StringUtils.lowerCase(columnName));

		final String[] split = StringUtil.str2Arr(columnName, "_");
		final StringBuffer objNameStr = new StringBuffer("");
		if ((split != null) && (split.length >= 1)) {
			for (final String string : split) {
				// 首字母大写
				objNameStr.append(StringUtils.capitalize(string));
			}
		}
		return StringUtils.uncapitalize(objNameStr.toString());
	}

	/**
	 * 对象属性转为数据库字段 <驼峰命名法，转为为字母全部大写，各单词之间有下划线>
	 *
	 * @param fieldName
	 *            属性名称
	 * @return 字段名称
	 */
	public static String fieldToColumn(final String fieldName) {
		final StringBuffer sb = new StringBuffer("");
		for (int i = 0; i < fieldName.length(); i++) {
			final char c = fieldName.charAt(i);
			if (Character.isUpperCase(c)) {
				sb.append("_" + c);
			} else {
				sb.append(c);
			}
		}
		return StringUtils.upperCase(sb.toString());
	}

	/**
	 * 是否MySQL数据库
	 *
	 * @return 是否
	 */
	public static boolean isMySQL() {
		if (SQLUtil.DB_MYSQL.equalsIgnoreCase(SQLUtil.dbType)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 是否Oracle数据库
	 *
	 * @return 是否
	 */
	public static boolean isOracle() {
		if (SQLUtil.DB_ORACLE.equalsIgnoreCase(SQLUtil.dbType)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 是否SQLServer数据库
	 *
	 * @return 是否
	 */
	public static boolean isSQLServer() {
		if (SQLUtil.DB_SQLSERVER.equalsIgnoreCase(SQLUtil.dbType)) {
			return true;
		} else {
			return false;
		}
	}

	public static String getDbType() {
		return SQLUtil.dbType;
	}

	public void setDbType(final String dbType) {
		Log.error("dbType = " + dbType);
		SQLUtil.dbType = dbType;
	}

	public static void main(final String[] args) {
		System.out.println(SQLUtil.replaceStr("mysql", " where 1=1 or '33223' "));
		//		String sql = StringUtils
		//				.trimToEmpty(" SElECT sfdsdf asdf asfd asdf asfd FROM ARTICLE ORDER BY model.STICK DESC, model.CREATE_TIME ASC, model.CREATE_TIME DESC,cta.SORT ASC,cta.SORT2 ASC");
		//		if (StringUtil.ignoreIndexOf(sql, "ORDER BY") >= 0) {
		//			String sqlBefore = StringUtils.substring(sql, 0, StringUtil.ignoreIndexOf(sql, "ORDER BY"));
		//			String order = StringUtils.substring(sql, StringUtil.ignoreIndexOf(sql, "ORDER BY"));
		//
		//			String reOrder = order.replaceAll("DESC", "ORDER_D");
		//			reOrder = reOrder.replaceAll("ASC", "ORDER_A");
		//
		//			// 统一将别名修改为model.
		//			reOrder = StringUtils.substringAfterIgnoreCase(reOrder, "ORDER BY");
		//			String[] fields = StringUtil.str2Arr(reOrder);
		//			if (fields != null && fields.length >= 0) {
		//				for (String field : fields) {
		//					String[] temps = StringUtil.str2Arr(field, ".");
		//					if (temps != null && temps.length >= 2) {
		//						reOrder = reOrder.replaceAll(temps[0] + ".", "model.");
		//					}
		//				}
		//			}
		//			reOrder = " ORDER BY " + reOrder;
		//			order = StringUtils.substringAfterIgnoreCase(order, "ORDER BY");
		//			fields = StringUtil.str2Arr(order);
		//			if (fields != null && fields.length >= 0) {
		//				for (String field : fields) {
		//					String[] temps = StringUtil.str2Arr(field, ".");
		//					if (temps != null && temps.length >= 2) {
		//						order = order.replaceAll(temps[0] + ".", "model.");
		//					}
		//				}
		//			}
		//			order = " ORDER BY " + order;
		//
		//			fields = StringUtils.substringsBetween(reOrder, "model.", " ORDER_");
		//			if (fields != null && fields.length >= 0) {
		//				for (String field : fields) {
		//					reOrder = reOrder.replaceAll(field, TableUtil.columnToField(field));
		//				}
		//			}
		//
		//			reOrder = reOrder.replaceAll("ORDER_D", "ASC");
		//			reOrder = reOrder.replaceAll("ORDER_A", "DESC");
		//
		//			System.out.println(sqlBefore);
		//			System.out.println(order);
		//			System.out.println(reOrder.replaceAll("model.", ""));
		//		}

	}
}
